(function ($) {
    if ($ === undefined) {
        if (console && console.error) { console.error("!!!yulu library required jQuery support!!!"); }
        return;
    }

    var namespace = function(str){
        if (str === undefined) {
            return window["yulu"];
        }
        var parts = str.split("."),
            parent = window["yulu"],
            i=0,
            l=0;

        if(parts[0]==="yulu"){
            parts = parts.slice(1);
        }
        for(i=0,l=parts.length; i<l;i++){
            if(typeof parent[parts[i]] === "undefined"){
                parent[parts[i]] = {};
            }
            parent = parent[parts[i]];
        }
        return parent;
    }

    var yulu = window["yulu"] = window["yulu"] || function(str) {
            return namespace(str);
        };

    var yuluCore = yulu("yulu.core");
    var objectClone = yuluCore.objectClone = function (obj) {
        // Handle the 3 simple types, and null or undefined
        if (null == obj || "object" != typeof obj) return obj;
        if (obj instanceof Date) {
            var copy = new Date();
            copy.setTime(obj.getTime());
            return copy;
        }
        if (obj instanceof RegExp) {
            return new RegExp(obj);
        }
        if (obj instanceof Array) {
            var copy = [];
            for (var i = 0, len = obj.length; i < len; ++i) {
                copy[i] = objectClone(obj[i]);
            }
            return copy;
        }
        if (obj instanceof Object) {
            var copy = {};
            for (var attr in obj) {
                if (obj.hasOwnProperty(attr)) copy[attr] = objectClone(obj[attr]);
            }
            return copy;
        }
        throw new Error("Unable to copy obj! Its type isn't supported.");
    }

    var wrapPropertiesPrefix = yuluCore.wrapPropertiesPrefix = function (obj, prefix) {
        var result = {};
        var reg = /\w/
        var replace = function(match) { return prefix ? prefix + match.toUpperCase() : match; };
        for (var k in obj) {
            var key = k.replace(reg, replace);
            result[key] = obj[k];
        }
        return result;
    }

    var trimPropertiesPrefix = yuluCore.trimPropertiesPrefix = function(obj, prefix, lowerFirst) {
        lowerFirst = lowerFirst === undefined ? true : !!lowerFirst;

        var result = {};
        var reg = lowerFirst ? new RegExp("^(" + prefix + ")" + "(\\w)") : new RegExp("^(" + prefix + ")");
        var replace = lowerFirst ? function(match, g1, g2) { return g2.toLowerCase(); } : function () { return ""; };
        for (var k in obj) {
            var key = k.replace(reg, replace);
            result[key] = obj[k];
        }
        return result;
    }

    var getDataOptions = yuluCore.getDataOptions = function (selector, prefix, trimPrefix) {
        var $selector = $(selector);
        var options = {};
        var datas = $selector.data();
        for (var k in datas) {
            if (k.indexOf(prefix) === 0) {
                options[k] = datas[k];
            }

        }
        return !!trimPrefix ? options : trimPropertiesPrefix(options, prefix);
    }

    var setDataOptions = yuluCore.setDataOptions = function (selector, val, prefix) {
        $(selector).data(wrapPropertiesPrefix(val, prefix))
    }

    var stringFormat = yuluCore.stringFormat = function(str, params) {
        return str.replace(/\{(\w+)\}/g, function(match, g) {
            if (params === undefined || params[g] === undefined) {
                return match;
            } else {
                return params[g];
            }
        });
    }

    var dateFormat = yuluCore.dateFormat = function (dateOrTimes, format) {
        format = format || "yyyy-MM-dd HH:mm:ss";
        var date = dateOrTimes;
        if (typeof(dateOrTimes) === "string") {
            if (!isNaN(dateOrTimes)) {
                date = new Date(Number.parseInt(dateOrTimes));
            }
        }
        if (typeof(dateOrTimes) === "number") {
            date = new Date(dateOrTimes);
        }
        if (!(date instanceof Date)) {
            if (console && console.debug) {
                console.debug("dateFormat only support typeof: Date, number");
            }
            return date;
        }
        var pattern = /(y{1,4})|(M{1,2})|(d{1,2})|(H{1,2})|(h{1,2})|(m{1,2})|(s{1,2})|(S{1,3})/g;
        var n = 0;
        var values = {
            "y": date.getFullYear(),
            "M": date.getMonth() + 1,
            "d": date.getDate(),
            "H": date.getHours(),
            "h": date.getHours() % 12,
            "m": date.getMinutes(),
            "s": date.getSeconds(),
            "S": date.getMilliseconds()
        }

        function rightString(str, length) {
            return new RegExp(".{" + length + "}$").exec(str);
        }

        var dateStr = format.replace(pattern, function(word) {
            if (values[word[0]] !== undefined) {
                return rightString("0000" + values[word[0]], word.length);
            } else {
                return word;
            }
        });
        return dateStr;
    }

    if (String.prototype.format === undefined) {
        String.prototype.format = function(params) {
            return stringFormat(this, params);
        }
    }
    if (Date.prototype.format === undefined) {
        Date.prototype.format = function (format) {
            return dateFormat(this, format);
        }
    }
	/*
	 if (Object.prototype.clone === undefined) {
	 Object.prototype.clone = function () {
	 return objectClone(this);
	 }
	 }
	 */
})(window.jQuery);
